package com.ccsu.eb.service;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ccsu.eb.config.AlipayConfig;
import com.ccsu.eb.constants.OrderStatus;
import com.ccsu.eb.mapper.EbOrderDetailMapper;
import com.ccsu.eb.mapper.EbOrderMapper;
import com.ccsu.eb.mapper.EbProductMapper;
import com.ccsu.eb.model.EbOrder;
import com.ccsu.eb.model.EbOrderDetail;
import com.ccsu.eb.model.EbProduct;
import com.ccsu.eb.model.EbUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * @Description: 用一句话描述
 * @Auther: 新梦想*陈超
 * @Date: 2022/3/21 14:07
 */
@Service
@Slf4j
public class CarService {
    @Resource
    private EbProductMapper ebProductMapper;
    @Resource
    private EbOrderMapper ebOrderMapper;

    @Resource
    private EbOrderDetailMapper orderDetailMapper;

    /**
     * 将商品加入到购物车
     *
     * @param pid     商品id
     * @param request http请求对象
     * @return
     */
    public boolean addCar(Integer pid, HttpServletRequest request) {
        EbProduct ebProduct = ebProductMapper.selectById(pid);
        if (ebProduct == null) {
            return false;
        }
        //TODO  1.购物车---session
        HttpSession car = request.getSession();
        //TODO  2.将商品放入到集合中
        //第1步：先从car取商品集合
        Set<EbProduct> productList = (Set<EbProduct>) car.getAttribute("car");
        //第2步：判断商品 集合是否存在
        if (productList == null) {//第1次添加商品到购物车
            productList = new HashSet<>();
        }
        //第 3步：将商品放入集合中
        for (EbProduct old : productList) {
            if (old.equals(ebProduct)) {
                ebProduct.setCount(old.getCount() + 1);//商品的购买数量进行累加
                //删除该商品
                productList.remove(old);
                break;
            }
        }
        BigDecimal currAmount = new BigDecimal("0.00");
        ebProduct.setAmount(currAmount.add(ebProduct.getEpPrice().multiply(new BigDecimal(ebProduct.getCount() + ""))));//设置商品的总价
        productList.add(ebProduct);//元素不存在才进行 添加
        System.out.println("购物车：" + productList);
        //TODO 4.将商品集合放入购物车
        car.setAttribute("car", productList);
        return true;
    }

    /**
     * 更新session商品的购买数量
     *
     * @param epId    商品id
     * @param newNums 新的 购买数量
     * @param request
     * @return
     */
    public boolean changeNum(Integer epId, Integer newNums, BigDecimal amount, HttpServletRequest request) {
        EbProduct ebProduct = ebProductMapper.selectById(epId);
        if (ebProduct == null) {
            return false;
        }
        //TODO  1.购物车---session
        HttpSession car = request.getSession();
        //TODO  2.从session获取购物车商品集合中
        //第1步：先从car取商品集合
        Set<EbProduct> productList = (Set<EbProduct>) car.getAttribute("car");
        //TODO 3.更新商品的购买数量
        for (EbProduct old : productList) {
            if (old.equals(ebProduct)) {
                ebProduct.setCount(newNums);//重置商品的购买数量

                //删除该商品
                productList.remove(old);
                break;
            }
        }
        BigDecimal currAmount = new BigDecimal("0.00");
        ebProduct.setAmount(currAmount.add(amount));//重置商品的总金额
        productList.add(ebProduct);//元素不存在才进行 添加
        System.out.println("购物车：" + productList);
        //TODO 4.将商品集合放入购物车
        car.setAttribute("car", productList);
        return true;
    }

    /**
     * 创建订单
     *
     * 问题1：事务问题
     *      @Transactional 事务注解 当该注解标记在某个方法 上，而这个在执行过程中，
     *      出现了运行时异常，则当前数据库事务会进行回滚！！！
     *问题2：超卖的问题
     *      mp乐观锁插件
     *优化点：
     *          数据库操作是不能放到循环里面的？
     * @return
     */
    @Transactional
    public String createOrder(HttpServletRequest request) {
        //TODO 1.参数校验---省略了 直接从session中 获取

        //TODO  2.获取购物车中所有商品列表
        Set<EbProduct> productSet = (Set<EbProduct>) request.getSession().getAttribute("car");
        //TODO  3.减库存---多个用户并发进行购买导致超卖
        for (EbProduct pro:productSet){
            EbProduct wareEbProduct = ebProductMapper.selectById(pro.getEpId());
            wareEbProduct.setEpStock(wareEbProduct.getEpStock()-pro.getCount());
            //需要优化为：批处理
            int reduceStockResult = ebProductMapper.update(
                    wareEbProduct, new UpdateWrapper<EbProduct>().eq("ep_id", pro.getEpId()));
            if(reduceStockResult<=0){
                throw new RuntimeException("扣减库存失败");
            }
        }
        log.info("===下单：商品库存扣减成功====");
        //TODO  4.创建订单
        BigDecimal amount = new BigDecimal("0.00");
        for (EbProduct ebProduct: productSet) {
            amount = amount.add(ebProduct.getEpPrice().multiply(new BigDecimal(ebProduct.getCount())));
        }
        EbOrder ebOrder =new EbOrder();
        ebOrder.setEoCreateTime(new Date());
        ebOrder.setEoCost(amount);
        ebOrder.setEoStatus(OrderStatus.ORDER_CREATED.getCode());
        EbUser lgnUser = (EbUser) request.getSession().getAttribute("lgnUser");
        if(lgnUser.getEuAddress()==null){
            throw new RuntimeException("下单失败，发货地址不能为 null");
        }
        ebOrder.setEoUserAddress(lgnUser.getEuAddress());
        ebOrder.setEoUserId(lgnUser.getEuUserId());
        ebOrder.setEoUserName(lgnUser.getEuUserName());
        ebOrder.setEoType(1);

        int insertResult = ebOrderMapper.insert(ebOrder);
        if(insertResult<=0){
            throw new RuntimeException("创建订单失败");
        }
        log.info("===下单：创建订单成功====");
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //int a = 10/0;//模拟异常
        ////////////////////////////////////////////////////////////////////////////////////////
        //TODO 5.创建订单详情
        for (EbProduct ebProduct: productSet) {
            EbOrderDetail orderDetail = new EbOrderDetail();
            amount = new BigDecimal("0.00");
            orderDetail.setEodCost(amount.add(ebProduct.getEpPrice().multiply(new BigDecimal(ebProduct.getCount()))));
            orderDetail.setEoId(ebOrder.getEoId());
            orderDetail.setEodQuantity(ebProduct.getCount());
            orderDetail.setEpId(ebProduct.getEpId());
            //需要优化为：批处理
            int insertReulst = orderDetailMapper.insert(orderDetail);
            if(insertResult<0){
                throw new RuntimeException("创建订单详情失败");
            }
        }
        log.info("===下单：创建订单详情成功====");
        //TODO 6.清空购物车
        request.getSession().removeAttribute("car");
        // TODO 7.发起支付
        return payOrder(ebOrder);
    }

    private String payOrder(EbOrder ebOrder) {
       try {
           //获得初始化的AlipayClient
           AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

           //设置请求参数
           AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
           alipayRequest.setReturnUrl(AlipayConfig.return_url);
           alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

           String orderTradeNo = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
           //商户订单号，商户网站订单系统中唯一订单号，必填
           String out_trade_no = new String(orderTradeNo.getBytes("UTF-8"),"UTF-8");
           //付款金额，必填
           String total_amount = new String(String.valueOf(ebOrder.getEoCost().doubleValue()).getBytes("ISO-8859-1"),"UTF-8");
           //订单名称，必填
           String subject = new String("kate的好东西".getBytes("UTF-8"),"UTF-8");
           //商品描述，可空
           String body = new String("好东西".getBytes("UTF-8"),"UTF-8");

           alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                   + "\"total_amount\":\""+ total_amount +"\","
                   + "\"subject\":\""+ subject +"\","
                   + "\"body\":\""+ body +"\","
                   + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
           //请求
           String result = alipayClient.pageExecute(alipayRequest).getBody();
           return  result;
       }catch (Exception e){
           e.printStackTrace();
       }
       return null;
    }


}
